import { IVec2, tween, Tween, Vec3, _decorator } from 'cc'
import { EntityManager } from '../../Base/EntityManager'
import { EntityTypeEnum, IBullet } from '../../Common'
import { EntityStateEnum, EventEnum } from '../../Enum'
import DataManager from '../../Global/DataManager'
import EventManager from '../../Global/EventManager'
import { ObjectPoolManager } from '../../Global/ObjectPoolManager'
import { radToAngle } from '../../Utils'
import { ExplosionManager } from '../Explosion/ExplosionManager'
import { BulletStateMachine } from './BulletStateMachine'
const { ccclass } = _decorator

// 子弹控制模块
@ccclass('BulletManager')
export class BulletManager extends EntityManager {
  // 子弹id
  id: number
  // 子弹类型
  type: EntityTypeEnum

  // 目标位置
  private targetPos: Vec3
  // 缓动动画
  private tw: Tween<unknown>

  // 初始化
  init(data: IBullet) {
    this.type = data.type
    this.id = data.id
    // 绑定有限状态机
    this.fsm = this.addComponent(BulletStateMachine)
    this.fsm.init(data.type)
    this.state = EntityStateEnum.Idle

    // 防止闪烁初始不可见
    this.node.active = false
    this.targetPos = undefined

    // 绑定子弹爆炸事件
    EventManager.Instance.on(EventEnum.ExplosionBorn, this.handleExplosionBorn, this)
  }

  // 处理子弹爆炸事件
  handleExplosionBorn(id: number, position: IVec2) {
    if (id !== this.id) return
    const explosion = ObjectPoolManager.Instance.get(EntityTypeEnum.Explosion)
    const em = explosion.getComponent(ExplosionManager) || explosion.addComponent(ExplosionManager)
    em.init(EntityTypeEnum.Explosion, position)

    this.ExplosionEnd()
  }

  // 爆炸结束
  ExplosionEnd() {
    EventManager.Instance.off(EventEnum.ExplosionBorn, this.handleExplosionBorn, this)
    DataManager.Instance.bulletMap.delete(this.id)
    ObjectPoolManager.Instance.ret(this.node)
  }

  // 渲染子弹
  render(data: IBullet) {
    this.renderPos(data)
    this.renderDir(data)
  }
  //  渲染子弹位置
  renderPos(data: IBullet) {
    const { position } = data
    const newPos = new Vec3(position.x, position.y)
    // 初始化目标点
    if (!this.targetPos) {
      this.node.active = true
      this.node.setPosition(newPos)
      this.targetPos = newPos
      // 有新目标时开始动画
    } else if (!this.targetPos.equals(newPos)) {
      // tween 动画设置缓动
      this.tw?.stop()
      this.targetPos = newPos
      this.tw = tween(this.node)
        .to(0.1, {
          position: this.targetPos,
        })
        .start()
    }
  }
  //  渲染子弹方向
  renderDir(data: IBullet) {
    const { direction } = data
    const angle = direction.x > 0 ? radToAngle(Math.asin(direction.y)) : 180 - radToAngle(Math.asin(direction.y)) // 单位向量:x**2+y**2=1
    this.node.setRotationFromEuler(0, 0, angle)
  }
}
